#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Odoo JSON-RPC Client - Read Hostel Students (简化版)
从 Odoo 服务器读取 hostel.student 模型的数据

使用方法：
  python3 read_students_simple.py
  
或使用命令行参数：
  python3 read_students_simple.py <username> <password> [database]
"""

import json
import urllib.request
import ssl
import sys
import getpass

# Odoo 服务器配置
ODOO_URL = "https://naturedao.tech/odoo"
DATABASE = "odootest"  # 从前面的测试中获取的数据库名

# 创建忽略 SSL 验证的上下文
ssl_context = ssl.create_default_context()
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE


def json_rpc(url, method, params):
    """执行 JSON-RPC 调用"""
    data = {
        "jsonrpc": "2.0",
        "method": method,
        "params": params,
        "id": 1,
    }
    
    req = urllib.request.Request(
        url=url,
        data=json.dumps(data).encode('utf-8'),
        headers={"Content-Type": "application/json"},
    )
    
    try:
        response = urllib.request.urlopen(req, context=ssl_context)
        result = json.loads(response.read().decode('utf-8'))
        
        # 调试：打印响应
        # print(f"DEBUG Response: {json.dumps(result, indent=2)}")
        
        if 'error' in result:
            return None, result['error']
        
        # 如果 result 是 False 或 None，也返回错误
        if result.get('result') is False or result.get('result') is None:
            return None, "Authentication failed: Invalid credentials"
        
        return result.get('result'), None
    
    except Exception as e:
        return None, str(e)


def authenticate(database, username, password):
    """身份验证"""
    print(f"正在验证用户 '{username}'...")
    print(f"  数据库: {database}")
    print(f"  URL: {ODOO_URL}/jsonrpc")
    
    result, error = json_rpc(
        f"{ODOO_URL}/jsonrpc",
        "call",
        {
            "service": "common",
            "method": "authenticate",
            "args": [database, username, password, {}]
        }
    )
    
    if result:
        print(f"✓ 验证成功！用户 ID: {result}")
        return result, None
    else:
        print(f"  错误详情: {error}")
        return None, error


def search_read_students(database, uid, password):
    """读取 hostel.student 模型的数据"""
    print("\n正在读取学生数据...")
    
    fields = [
        'id', 'name', 'gender', 'class_id', 'room_id', 'hostel_id',
        'check_in_date', 'check_out_date', 'stay_duration', 'status', 'active',
    ]
    
    result, error = json_rpc(
        f"{ODOO_URL}/jsonrpc",
        "call",
        {
            "service": "object",
            "method": "execute_kw",
            "args": [
                database, uid, password,
                "hostel.student", "search_read",
                [],  # domain: [] 表示所有记录
                {
                    "fields": fields,
                    "limit": 100,
                    "order": "id desc",
                }
            ]
        }
    )
    
    return result, error


def print_students(students):
    """格式化打印学生数据（表格形式）"""
    if not students:
        print("\n没有找到任何学生记录。")
        return
    
    print(f"\n找到 {len(students)} 条学生记录：")
    print("=" * 125)
    
    # 表头
    header = f"{'ID':<6} {'姓名':<20} {'性别':<8} {'班级':<18} {'房间':<22} {'状态':<12} {'入住日期':<12}"
    print(header)
    print("-" * 125)
    
    # 数据行
    for student in students:
        # 处理 Many2one 字段
        room_name = student.get('room_id')[1] if student.get('room_id') else "未分配"
        
        # 性别翻译
        gender_map = {'male': '男', 'female': '女', 'other': '其他'}
        gender = gender_map.get(student.get('gender', ''), student.get('gender', ''))
        
        # 状态翻译
        status_map = {
            'draft': '草稿',
            'reservation': '预订',
            'pending': '待定',
            'paid': '已付款',
            'discharge': '已退房',
            'cancel': '已取消'
        }
        status = status_map.get(student.get('status', ''), student.get('status', ''))
        
        # 日期
        check_in_date = student.get('check_in_date', '') or ''
        
        # 打印行
        row = (
            f"{student.get('id', ''):<6} "
            f"{student.get('name', ''):<20} "
            f"{gender:<8} "
            f"{student.get('class_id', ''):<18} "
            f"{room_name:<22} "
            f"{status:<12} "
            f"{check_in_date:<12}"
        )
        print(row)
    
    print("=" * 125)


def print_student_json(students, limit=3):
    """以 JSON 格式打印学生详细信息"""
    print(f"\n\nJSON 格式详细信息（前 {min(limit, len(students))} 条）：")
    print("=" * 80)
    
    for student in students[:limit]:
        print(json.dumps(student, ensure_ascii=False, indent=2))
        print("-" * 80)


def print_statistics(students):
    """打印统计信息"""
    if not students:
        return
    
    print("\n\n统计信息：")
    print("=" * 80)
    
    # 性别统计
    gender_count = {}
    for student in students:
        gender = student.get('gender', 'unknown')
        gender_count[gender] = gender_count.get(gender, 0) + 1
    
    print("性别分布：")
    for gender, count in gender_count.items():
        gender_map = {'male': '男', 'female': '女', 'other': '其他'}
        print(f"  {gender_map.get(gender, gender)}: {count} 人")
    
    # 状态统计
    status_count = {}
    for student in students:
        status = student.get('status', 'unknown')
        status_count[status] = status_count.get(status, 0) + 1
    
    print("\n状态分布：")
    status_map = {
        'draft': '草稿', 'reservation': '预订', 'pending': '待定',
        'paid': '已付款', 'discharge': '已退房', 'cancel': '已取消'
    }
    for status, count in status_count.items():
        print(f"  {status_map.get(status, status)}: {count} 人")
    
    # 房间分配统计
    with_room = sum(1 for s in students if s.get('room_id'))
    without_room = len(students) - with_room
    
    print(f"\n房间分配：")
    print(f"  已分配: {with_room} 人")
    print(f"  未分配: {without_room} 人")
    
    print("=" * 80)


def main():
    """主函数"""
    print("=" * 80)
    print("Odoo JSON-RPC Client - 读取宿舍学生数据")
    print("=" * 80)
    print(f"服务器: {ODOO_URL}")
    print(f"数据库: {DATABASE}")
    print("=" * 80)
    
    # 获取用户名和密码
    if len(sys.argv) >= 3:
        username = sys.argv[1]
        password = sys.argv[2]
        if len(sys.argv) >= 4:
            database = sys.argv[3]
        else:
            database = DATABASE
    else:
        print("\n请输入 Odoo 登录凭据：")
        username = input("用户名 (默认: admin): ").strip() or "admin"
        password = getpass.getpass("密码: ")
        database = DATABASE
    
    print(f"\n数据库: {database}")
    print(f"用户名: {username}")
    print("=" * 80)
    
    try:
        # 1. 身份验证
        uid, error = authenticate(database, username, password)
        
        if not uid:
            print(f"\n✗ 验证失败: {error}")
            print("\n提示：请确认用户名和密码是否正确")
            return
        
        # 2. 读取学生数据
        students, error = search_read_students(database, uid, password)
        
        if error:
            print(f"\n✗ 读取数据失败: {error}")
            return
        
        if not students:
            print("\n没有找到任何学生记录。")
            return
        
        # 3. 打印数据
        print_students(students)
        print_statistics(students)
        print_student_json(students, limit=2)
        
        print("\n✓ 数据读取完成！")
        print(f"\n数据库: {database}")
        print(f"总记录数: {len(students)}")
        print("=" * 80)
        
    except Exception as e:
        print(f"\n✗ 错误: {str(e)}")
        import traceback
        traceback.print_exc()


if __name__ == "__main__":
    main()

